package multi_thread.master.executors;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author Cheng Jun
 * Description: 一个Executor，它提供了一些方法来管理终止，以及一些方法可以生成一个Future来跟踪一个或多个异步任务的进度。
 *     invokeAll invokeAny 都能提交任务，让 Executor 去执行，但是提交任务集合后，再去改变这个集合，并不一定能新增或减少任务 所以，这两个方法
 *     适合任务集合提前确定的场景。通常，还是遵循 Runnable 使用 exectue 提交，Callable 使用 submit 提交
 * @version 1.0
 * @date 2021/10/10 16:48
 * @see ExecutorService
 */
public class ExecutorServiceExample {

  public static void main(String[] args) throws ExecutionException, InterruptedException {

    ExecutorService executorService = Executors.newFixedThreadPool(10);
    List<Callable<String>> taskList = new ArrayList<>(16);
    taskList.add(
        () -> {
          System.out.println("Task 1 ..........running.......");
          return "Task 1";
        });
    taskList.add(
        () -> {
          TimeUnit.SECONDS.sleep(1);
          System.out.println("Task 2 ..........running.......");
          return "Task 2";
        });
    taskList.add(
        () -> {
          System.out.println("Task 3 ..........running.......");
          return "Task 3";
        });

    // 返回RunnableFuture的list集合，看源码 RunnableFuture<T> f = newTaskFor(t);
    List<Future<String>> futures = executorService.invokeAll(taskList);
    for (Future<String> future : futures) {
      System.out.println(future.get());
    }
    System.out.println("阻塞式，等待线程池中的线程执行完任务");
    // invokeAny 3个线程中最快的那个会返回，但是其他的也可能都执行完/也可能不执行；
    // 从源码（java.util.concurrent.AbstractExecutorService.doInvokeAny）可以看出，第一个任务更有可能首先完成
    // String result = executorService.invokeAny(taskList);
    // System.out.println("result = " + result);

    // 关闭线程池
    executorService.shutdown();
  }
}
